#include "stdafx.h"
#include "CConvWrapper.h"

CONVERTER_DLL();

	
#ifdef _DEBUG
#	define CONVERTER_DLL_NAME	"..\\..\\bin\\utils\\Converter.dll"
#else
#	define CONVERTER_DLL_NAME	"Converter.dll"
#endif

	
#ifdef _DEBUG
#	include <crtdbg.h>
#	define ASSERT( _b_val )					_ASSERTE( _b_val )
#	define ASSERT_EXT( _b_val, _p_msg )		_ASSERT_EXPR( _b_val, __CRT_WIDE(_p_msg) )
#else
#	define ASSERT( _b_val )
#	define ASSERT_EXT( _b_val, _p_msg )
#endif	// _DEBUG


#pragma warning (push)
#pragma warning (disable: 4996)		// this function or variable may be unsafe


//
// CLI String
//

struct TCLIString
{
private:
	char	*_pCStr;

public:
	TCLIString(String ^str): _pCStr(nullptr)
	{
		_pCStr = (char *)(void*)Marshal::StringToHGlobalAnsi( str );
	}

	~TCLIString()
	{
		Marshal::FreeHGlobal( (System::IntPtr) (void *)_pCStr );
	}

	operator char * () const
	{
		return _pCStr;
	}
};


inline const char * GetFileName(char * pcName)
{
	isize	ext = 0;

	for (isize i = strlen(pcName)-1; i >= 0; --i)
	{
		if ( pcName[i] == '.' && ext == 0 )
			ext = i;

		if ( pcName[i] == '\\' || pcName[i] == '/' ) {
			pcName[ext] = '\0';
			return pcName + i + 1;
		}
	}

	pcName[ext] = '\0';
	return pcName;
}



CConvWrapper::CConvWrapper():
	_pConverter(nullptr),	_pTexture(nullptr),		_pFont(nullptr),
	_pSprite(nullptr),		_pModel(nullptr),		_pSound(nullptr),
	_pVideo(nullptr),		_pTerrain(nullptr),
	_uLayer(-1),				_uMipmap(-1),			_bMipmapList(true),
	_uSprNumb(0),			_uAnimNumb(-1),			_bTexLoaded(false),
	_bIsInited(false),		_uSelected(0),			_eSelectedGroup(MC_UNKNOWN)
{
	if ( GetConverter( CONVERTER_DLL_NAME, _pConverter ) )
	{
		bool	res = true;

		res &= _pConverter->GetSubSystem( SST_TEXTURE_CONVERTER,		(ISubSystem *&)_pTexture )	== S_OK;
		res &= _pConverter->GetSubSystem( SST_FONT_CONVERTER,		(ISubSystem *&)_pFont )		== S_OK;
		res &= _pConverter->GetSubSystem( SST_SPRITE_CONVERTER,		(ISubSystem *&)_pSprite )	== S_OK;
		res &= _pConverter->GetSubSystem( SST_MODEL_CONVERTER,		(ISubSystem *&)_pModel )	== S_OK;
		res &= _pConverter->GetSubSystem( SST_SOUND_CONVERTER,		(ISubSystem *&)_pSound )	== S_OK;
		res &= _pConverter->GetSubSystem( SST_VIDEO_CONVERTER,		(ISubSystem *&)_pVideo )	== S_OK;
		res &= _pConverter->GetSubSystem( SST_TERRAIN_CONVERTER,		(ISubSystem *&)_pTerrain )	== S_OK;

		_bIsInited = true;
	}
}


CConvWrapper::~CConvWrapper()
{
	FreeConverter( _pConverter );

	_pConverter		= nullptr;
	_pTexture		= nullptr;
	_pFont			= nullptr;
	_pSprite		= nullptr;
	_pModel			= nullptr;
	_pSound			= nullptr;
	_pVideo			= nullptr;
	_pTerrain		= nullptr;
}


int CConvWrapper::StrToInt(String ^pStr)
{
	TCLIString	str( pStr );
	return atoi(str);
}


int CConvWrapper::StrToInt16(String ^pStr)
{
	TCLIString	str( gcnew String("0x") + pStr );
	return atoi(str);
}


void CConvWrapper::IntToStr(int iValue, String ^&pStr, int iRadix)
{
	char	a_buf[30];
	pStr = gcnew String( _itoa( iValue, a_buf, iRadix ) );
}


float CConvWrapper::StrToFloat(String ^pStr)
{
	TCLIString	str(pStr);
	return (float)atof(str);
}


void CConvWrapper::FloatToStr(float fValue, String ^&pStr)
{
	char	a_buf[50];
	
	if ( sprintf_s( a_buf, 50, "%0.6f", fValue ) != -1 )
	{
		pStr = gcnew String( a_buf );
	}
}


bool CConvWrapper::GetVersion(String ^&pStr)
{
	uint	major = 0,
			minor = 0;

	bool	ret = _pConverter->GetVersion( major, minor ) == S_OK;
	ASSERT( ret && "can't get converter version" );

	if ( ret )
	{
		char			a_buf[30];
		std::string		str;

		str += _itoa( major, a_buf, 10 );
		str += '.';
		str += _itoa( minor, a_buf, 10 );

		pStr = gcnew String( str.c_str() );
	}
	return ret;
}


bool CConvWrapper::GetErrors(ListBox ^pList, bool &bNewErrors)
{
	const uint	u_buf_size = 255;
	char		a_buffer[u_buf_size];
	uint		u_count = 0;
	uint		u_written = 0;

	bNewErrors = false;

	bool	ret = _pConverter->GetErrorsCount( u_count ) == S_OK;
	ASSERT( ret && "can't get errors count" );

	if ( ret && u_count != 0 )
	{
		bNewErrors = true;

		for (uint i = 0; i < u_count; ++i)
		{
			ret = _pConverter->GetErrorString( a_buffer, u_buf_size, u_written ) == S_OK;
			ASSERT( ret && "can't get error string" );

			if ( !ret )
				break;

			pList->Items->Add( gcnew String( a_buffer ) );
		}
	}

	return ret;
}



//////////////////////// TEXTURE //////////////////////////

bool CConvWrapper::GetSupportedTextureFormats(String ^&pStr)
{
	const uint	u_buf_size = 255;
	char		a_buffer[u_buf_size];

	bool	ret = _pTexture->GetSupportedFormats( a_buffer, u_buf_size ) == S_OK;
	ASSERT( ret && "can't get supported texture formats" );

	if ( ret ) {
		pStr = gcnew String( a_buffer );
		pStr += L"|all files|*.*";
	}

	return ret;
}


void CConvWrapper::GetTextureInternalFormatsList(ComboBox ^pComboBox)
{
	const uint	u_buf_size = 255;
	char		a_buffer[u_buf_size];
	HRESULT		res = S_OK;

	pComboBox->Items->Clear();

	for (uint i = 1;; ++i)
	{
		res = _pTexture->GetInternalFormatName( i, a_buffer, u_buf_size );

		if ( res != S_OK )
			break;

		pComboBox->Items->Add( gcnew String( a_buffer ) );
	}
}


void CConvWrapper::GetTextureColorFormatsList(ComboBox ^pComboBox)
{
	const uint	u_buf_size = 255;
	char		a_buffer[u_buf_size];
	HRESULT		res = S_OK;

	pComboBox->Items->Clear();

	for (uint i = 1;; ++i)
	{
		res = _pTexture->GetColorFormatName( i, a_buffer, u_buf_size );

		if ( res != S_OK )
			break;

		pComboBox->Items->Add( gcnew String( a_buffer ) );
	}
}


void CConvWrapper::GetTextureColorValueTypesList(ComboBox ^pComboBox)
{
	const uint	u_buf_size = 255;
	char		a_buffer[u_buf_size];
	HRESULT		res = S_OK;

	pComboBox->Items->Clear();

	for (uint i = 1;; ++i)
	{
		res = _pTexture->GetColorTypeName( i, a_buffer, u_buf_size );

		if ( res != S_OK )
			break;

		pComboBox->Items->Add( gcnew String( a_buffer ) );
	}
}


bool CConvWrapper::CreateTexture(E_TEXTURE_TYPE eType)
{
	_bTexLoaded = false;
	bool	ret = _pTexture->Create( eType ) == S_OK;
	ASSERT( ret && "can't create texture" );
	return ret;
}


bool CConvWrapper::DeleteTexture()
{
	_bTexLoaded = false;
	bool	ret = _pTexture->Delete() == S_OK;
	ASSERT( ret && "can't delete texture" );
	return ret;
}


bool CConvWrapper::LoadTexture(String ^pStr)
{
	TCLIString	str(pStr);

	bool	ret = _pTexture->Load( str ) == S_OK;
	ASSERT( ret && "can't load texture" );
	_bTexLoaded = ret;

	return ret;
}


bool CConvWrapper::SaveTexture(String ^pStr)
{
	TCLIString	str(pStr);

	bool	ret = _pTexture->Save( str ) == S_OK;
	ASSERT( ret && "can't save texture" );

	return ret;
}


void CConvWrapper::SelectTexture(uint uNumb)
{
	if ( _bMipmapList ) {
		_uMipmap = uNumb;
	}
	else {
		_uMipmap = 0;
		_uLayer  = uNumb;
	}
}


void CConvWrapper::SelectTextureMode(bool bMipmaps)
{
	_bMipmapList = bMipmaps;
}


bool CConvWrapper::AddTexture(String ^pStr)
{
	TCLIString	str(pStr);

	bool	ret		= true;
	uint	u_num	= 0;

	if ( _bMipmapList )
		ret = _pTexture->LoadMipmap( str, _uLayer, u_num ) == S_OK;
	else
		ret = _pTexture->LoadLayer( str, u_num ) == S_OK;

	ASSERT( ret && "can't add texture" );
	return ret;
}


bool CConvWrapper::RemoveTexture()
{
	bool	ret = true;

	if ( _bMipmapList )
		ret = _pTexture->RemoveLayer( _uLayer ) == S_OK;
	else
		ret = _pTexture->RemoveMipmap( _uLayer, _uMipmap ) == S_OK;

	ASSERT( ret && "can't remove texture" );
	return ret;
}


bool CConvWrapper::UpTextureLayer()
{
	bool	ret = false;

	if ( !_bMipmapList )
		ret = _pTexture->SwapLayers( _uLayer, _uLayer+1 ) == S_OK;

	ASSERT( ret && "can't up texture" );
	return ret;
}


bool CConvWrapper::DownTextureLayer()
{
	bool	ret = false;

	if ( !_bMipmapList )
		ret = _pTexture->SwapLayers( _uLayer, _uLayer-1 ) == S_OK;

	ASSERT( ret && "can't down texture" );
	return ret;
}


bool CConvWrapper::GetTextureName(String ^&pStr)
{
	const uint	u_buf_size = 255;
	char		a_buffer[u_buf_size];
	
	bool	ret = _pTexture->GetName( _uLayer, _uMipmap, a_buffer, u_buf_size ) == S_OK;
	ASSERT( ret && "can't get texture name" );
	
	if ( ret )
		pStr = gcnew String( a_buffer );

	return ret;
}


bool CConvWrapper::GetMainTextureName(String ^&pStr)
{
	const uint	u_buf_size = 255;
	char		a_buffer[u_buf_size];
	
	bool	ret = _pTexture->GetName( 0, 0, a_buffer, u_buf_size ) == S_OK;
	ASSERT( ret && "can't get texture name" );
	
	if ( ret )
		pStr = gcnew String( GetFileName( a_buffer ) );

	return ret;
}


void CConvWrapper::GetTextureNames(ListBox ^pList)
{
	const uint	u_buf_size = 255;
	char		a_buffer[u_buf_size];
	HRESULT		res = S_OK;

	pList->Items->Clear();

	if ( _bMipmapList )
	{
		for (uint i = 0;; ++i)
		{
			res = _pTexture->GetName( _uLayer, i, a_buffer, u_buf_size );

			if ( res != S_OK )
				break;

			pList->Items->Add( gcnew String( a_buffer ) );
		}
	}
	else
	{
		for (uint i = 0;; ++i)
		{
			res = _pTexture->GetName( i, 0, a_buffer, u_buf_size );

			if ( res != S_OK )
				break;

			pList->Items->Add( gcnew String( a_buffer ) );
		}
	}
}


bool CConvWrapper::GetTextureInfo(String ^&pStr)
{
	const uint	u_buf_size = 255;
	char		a_buffer[u_buf_size];

	bool	ret = _pTexture->GetInfo( a_buffer, u_buf_size ) == S_OK;
	ASSERT( ret && "can't get texture info" );

	if ( ret )
		pStr = gcnew String( a_buffer );

	return ret;
}


bool CConvWrapper::GetTextureFormat(TTextureFormat &sFormat)
{
	bool	ret = _pTexture->GetFormat( sFormat ) == S_OK;
	ASSERT( ret && "can't get texture format" );
	return ret;
}


bool CConvWrapper::SetTextureFormat(const TTextureFormat &sFormat)
{
	bool	ret = _pTexture->SetFormat( sFormat ) == S_OK;
	ASSERT( ret && "can't set texture format" );
	return ret;
}



///////////////////////// MODEL ///////////////////////////

bool CConvWrapper::GetSupportedModelFormats(String ^&pStr)
{
	const uint	u_buf_size = 255;
	char		a_buffer[u_buf_size];

	bool	ret = _pModel->GetSupportedFormats( a_buffer, u_buf_size ) == S_OK;
	ASSERT( ret && "can't get supported model formats" );

	if ( ret ) {
		pStr = gcnew String( a_buffer );
		pStr += L"|all files|*.*";
	}

	return ret;
}


const char * CConvWrapper::GetAttribName(E_VERTEX_ATTRIBUTE eAttrib)
{
	static const char	*a_attribs[] = {
		"unknown",
		"position",
		"normal",
		"texcoord_0",
		"texcoord_1",
		"texcoord_2",
		"texcoord_3",
		"texcoord_4",
		"texcoord_5",
		"texcoord_6",
		"texcoord_7",
		"texcoord_8",
		"texcoord_9",
		"texcoord_10",
		"texcoord_11",
		"texcoord_12",
		"texcoord_13",
		"texcoord_14",
		"texcoord_15"
	};
	static const uint	u_attr_count = sizeof(a_attribs) / sizeof(a_attribs[0]);

	if ( eAttrib >= u_attr_count )	return a_attribs[0];
	else							return a_attribs[eAttrib];
}


const char * CConvWrapper::GetValueName(E_VERTEX_VALUE_TYPE eValue)
{
	static const char	*a_values[] = {
		"unknown",
		"half",
		"float",
		"double",
		"fixed",
		"int8",
		"int16",
		"int32",
		"uint8",
		"uint16",
		"uint32"
	};
	static const uint	u_val_count = sizeof(a_values) / sizeof(a_values[0]);

	eValue = E_VERTEX_VALUE_TYPE( eValue & VT_TYPE_MASK);

	if ( eValue >= u_val_count )	return a_values[0];
	else							return a_values[eValue];
}


void CConvWrapper::GetVertexAttribsList(ComboBox ^pCombo)
{
	pCombo->Items->Clear();

	for (uint i = 0; i < VA_COUNT; ++i)
	{
		pCombo->Items->Add( gcnew String( GetAttribName( (E_VERTEX_ATTRIBUTE)i ) ) );
	}
}


void CConvWrapper::GetVertexValuesList(ComboBox ^pCombo)
{
	pCombo->Items->Clear();

	for (uint i = 0; i < VT_TYPES_COUNT; ++i)
	{
		pCombo->Items->Add( gcnew String( GetValueName( (E_VERTEX_VALUE_TYPE)i ) ) );
	}
}


bool CConvWrapper::DeleteModel()
{
	bool	ret = _pModel->Delete() == S_OK;
	ASSERT( ret && "can't delete model" );
	return ret;
}


bool CConvWrapper::LoadModel(String ^pStr, E_MODEL_COMPONENT eComp)
{
	TCLIString	str(pStr);

	bool	ret = _pModel->Load( str, eComp ) == S_OK;
	ASSERT( ret && "can't load model" );
	return ret;
}


bool CConvWrapper::SaveModel(String ^pStr, E_MODEL_COMPONENT eComp)
{
	TCLIString	str(pStr);

	bool	ret = _pModel->Save( str, eComp ) == S_OK;
	ASSERT( ret && "can't save model" );
	return ret;
}


void CConvWrapper::MergeModelComponents(E_MODEL_COMPONENT eType)
{
	bool	ret = _pModel->MergeComponents( eType ) == S_OK;
	ASSERT( ret && "can't merge components" );
}


void CConvWrapper::RemoveModelComponent(E_MODEL_COMPONENT eType, uint uIndex)
{
	bool	ret = _pModel->Remove( eType, uIndex ) == S_OK;
	ASSERT( ret && "can't remove component" );
}


bool CConvWrapper::GetModelType(E_MODEL_TYPE &eType)
{
	bool	ret = _pModel->GetModelType( eType ) == S_OK;
	ASSERT( ret && "can't get model type" );
	return ret;
}


bool CConvWrapper::SetModelType(E_MODEL_TYPE eType)
{
	bool	ret = _pModel->SetModelType( eType ) == S_OK;
	ASSERT( ret && "can't set model type" );
	return ret;
}


void CConvWrapper::SelectModelComponent(E_MODEL_COMPONENT eComp, uint uIndex)
{
	_eSelectedGroup = eComp;
	_uSelected		= uIndex;
}

	
bool CConvWrapper::UpdateMeshAttribs()
{
	const uint		uAttribsCount			= 25;
	TMeshVertices	aAttribs[uAttribsCount];
	uint			uWritten				= 0;

	_aAttribs.clear();

	bool	ret = _pModel->GetAttribValues( aAttribs, uAttribsCount, uWritten ) == S_OK;
	ASSERT( ret );

	if ( ret )
	{
		for (uint i = 0; i < uWritten; ++i)
		{
			TAttrib		s_attr;

			s_attr.sVert = aAttribs[i];
			
			bool	r = true;

			s_attr.sText  = GetAttribName( s_attr.sVert.eAttrib );
			s_attr.sText += " - ";
			s_attr.sText += GetValueName( s_attr.sVert.eValue );

			_aAttribs.push_back( s_attr );
		}
	}

	return ret;
}


bool CConvWrapper::SetMeshAttribs()
{
	std::vector<TMeshVertices>	a_attribs;

	for (size_t i = 0; i < _aAttribs.size(); ++i)
		a_attribs.push_back( _aAttribs[i].sVert );

	bool	ret = _pModel->SetAttribValues( &a_attribs[0], a_attribs.size() ) == S_OK;
	ASSERT( ret );

	return ret;
}


void CConvWrapper::GetMeshAttribs(ListBox ^pList)
{
	pList->Items->Clear();

	for (size_t i = 0; i < _aAttribs.size(); ++i)
	{
		pList->Items->Add( gcnew String( _aAttribs[i].sText.c_str() ) );
	}
}


bool CConvWrapper::AddMeshAttrib(uint uAttrib, uint uValue, float fScale, bool bNormalize, bool bNormalized, bool bScale, uint uIndex)
{
	TAttrib		s_attr;

	s_attr.sVert.eAttrib = (E_VERTEX_ATTRIBUTE)uAttrib;
	s_attr.sVert.eValue  = (E_VERTEX_VALUE_TYPE)uValue;
	s_attr.sVert.fScale  = fScale;
			
	bool	r = true;

	s_attr.sText  = GetAttribName( s_attr.sVert.eAttrib );
	s_attr.sText += " - ";
	s_attr.sText += GetValueName( s_attr.sVert.eValue );

	if ( uIndex >= _aAttribs.size() )
		_aAttribs.push_back( s_attr );
	else
		_aAttribs[uIndex] = s_attr;

	return true;
}


bool CConvWrapper::RemoveMeshAttrib(uint uIndex)
{
	if ( uIndex >= _aAttribs.size() )
		return false;

	_aAttribs.erase( _aAttribs.begin() + uIndex );
	return true;
}


void CConvWrapper::ApplyMeshChanges()
{
	bool	ret = _pModel->ApplyToMesh( _uSelected ) == S_OK;
	ASSERT( ret && "can't apply parameters to mesh" );
}


void CConvWrapper::GetModelComponentsNames(ListBox ^pList, E_MODEL_COMPONENT eComp)
{
	const uint	u_buf_size	= 255;
	uint		u_count		= 0;
	char		a_buffer[u_buf_size];
	HRESULT		res = S_OK;

	res = _pModel->GetComponentsCount( eComp, u_count );
	ASSERT( res == S_OK );

	pList->Items->Clear();

	for (uint i = 0; i < u_count; ++i)
	{
		res = _pModel->GetComponent( i, eComp, a_buffer, u_buf_size );

		if ( res != S_OK )
			break;

		pList->Items->Add( gcnew String( a_buffer ) );
	}
}


bool CConvWrapper::SetModelOptimizeParams(uint uCashSize, float fAccuracy, E_MESH_FLAGS eFlags, E_MESH_VERT_PACK ePackType)
{
	bool	ret = _pModel->SetOptimizeParams( uCashSize, fAccuracy, eFlags, ePackType ) == S_OK;
	ASSERT( ret && "can't set model params" );
	return ret;
}


bool CConvWrapper::GetModelOptimizeParams(uint &uCashSize, float &fAccuracy, E_MESH_FLAGS &eFlags, E_MESH_VERT_PACK &ePackType)
{
	bool	ret = _pModel->GetOptimizeParams( uCashSize, fAccuracy, eFlags, ePackType ) == S_OK;
	ASSERT( ret && "can't get model params" );
	return ret;
}


///////////////////////// FONT ////////////////////////////

bool CConvWrapper::GetSupportedFontFormats(String ^&pStr)
{
	const uint	u_buf_size = 255;
	char		a_buffer[u_buf_size];

	bool	ret = _pFont->GetSupportedFormats( a_buffer, u_buf_size ) == S_OK;
	ASSERT( ret && "can't get supported font formats" );

	if ( ret ) {
		pStr = gcnew String( a_buffer );
		pStr += L"|all files|*.*";
	}

	return ret;
}


bool CConvWrapper::CreateFont()
{
	bool	ret = _pFont->Create() == S_OK;
	ASSERT( ret && "can't create font" );
	_sFontName.clear();
	return ret;
}


bool CConvWrapper::DeleteFont()
{
	bool	ret = _pFont->Delete() == S_OK;
	ASSERT( ret && "can't delete font" );
	_sFontName.clear();
	return ret;
}

	
bool CConvWrapper::GetFontName(String ^&pStr)
{
	if ( _sFontName.empty() )
		return false;

	pStr = gcnew String( _sFontName.c_str() );
	return true;
}


bool CConvWrapper::LoadFont(String ^pStr)
{
	TCLIString	str(pStr);

	bool	ret = _pFont->Load( str ) == S_OK;
	ASSERT( ret && "can't load font" );

	if ( ret )
		_sFontName = GetFileName( str );

	return ret;
}


bool CConvWrapper::SaveFont(String ^pStr)
{
	TCLIString	str(pStr);

	bool	ret = _pFont->Save( str ) == S_OK;
	ASSERT( ret && "can't save font" );
	
	return ret;
}


bool CConvWrapper::SetFontOffsets(uint uASCII, uint uUnicode)
{
	bool	ret1 = _pFont->SetASCOffset( uASCII ) == S_OK;
	ASSERT( ret1 && "can't set ASCII offset to font" );

	bool	ret2 = _pFont->SetUnicodeOffset( uUnicode ) == S_OK;
	ASSERT( ret2 && "can't set UNICODE offset to font" );

	return ret1 && ret2;
}


bool CConvWrapper::GetFontOffsets(uint &uASCII, uint &uUnicode)
{
	bool	ret1 = _pFont->GetASCOffset( uASCII ) == S_OK;
	ASSERT( ret1 && "can't get ASCII offset to font" );

	bool	ret2 = _pFont->GetUnicodeOffset( uUnicode ) == S_OK;
	ASSERT( ret2 && "can't get UNICODE offset to font" );

	return ret1 && ret2;
}


bool CConvWrapper::SetFontCharsCount(uint uCount)
{
	bool	ret = _pFont->SetCharsCount( uCount ) == S_OK;
	ASSERT( ret && "can't set font chars count" );
	return ret;
}


bool CConvWrapper::GetFontCharsCount(uint &uCount)
{
	bool	ret = _pFont->GetCharsCount( uCount ) == S_OK;
	ASSERT( ret && "can't get font chars count" );
	return ret;
}



/////////////////////// SPRITE ////////////////////////////

bool CConvWrapper::GetSupportedSpriteFormats(String ^&pStr)
{
	const uint	u_buf_size = 255;
	char		a_buffer[u_buf_size];

	bool	ret = _pSprite->GetSupportedFormats( a_buffer, u_buf_size ) == S_OK;
	ASSERT( ret && "can't get supported sprite formats" );

	if ( ret ) {
		pStr = gcnew String( a_buffer );
		pStr += L"|all files|*.*";
	}

	return ret;
}


bool CConvWrapper::GetSpriteName(String ^&pStr)
{
	if ( _sSpriteName.empty() )
		return false;

	pStr = gcnew String( _sSpriteName.c_str() );
	return false;
}


bool CConvWrapper::CreateSprite()
{
	bool	ret = _pSprite->Create() == S_OK;
	ASSERT( ret && "can't create sprite" );
	return ret;
}


bool CConvWrapper::DeleteSprite()
{
	bool	ret = _pSprite->Delete() == S_OK;
	ASSERT( ret && "can't delete sprite" );
	_sSpriteName.clear();
	return ret;
}


bool CConvWrapper::BuildSprite()
{
	bool	ret = _pSprite->Build() == S_OK;
	ASSERT( ret && "can't build sprite" );
	return ret;
}


bool CConvWrapper::SaveSprite(String ^pStr)
{
	TCLIString	str(pStr);

	bool	ret = _pSprite->Save( str ) == S_OK;
	ASSERT( ret && "can't save sprite" );
	
	return ret;
}


void CConvWrapper::SelectSprite(uint uNumb)
{
	_uSprNumb = uNumb;
}


void CConvWrapper::SelectAnimation(uint uAnim)
{
	uint	u_count = 0;
	bool	ret = _pSprite->GetAnimationCount( _uSprNumb, u_count ) == S_OK;
	ASSERT( ret && "can't get sprite animations count" );

	if ( ret )
	{
		if ( uAnim < u_count )
			_uAnimNumb = uAnim;
		else {
			_uAnimNumb = -1;
			ASSERT( false && "wrong animation number" );
		}
	}
}


bool CConvWrapper::AddSpriteTexture(String ^pStr)
{
	TCLIString	str(pStr);
	uint		u_numb = 0;

	bool	ret = _pSprite->AddTexture( str, u_numb ) == S_OK;
	ASSERT( ret && "can't load sprite texture" );

	if ( ret && _sSpriteName.empty() )
		_sSpriteName = GetFileName( str );

	return ret;
}


bool CConvWrapper::RemoveSpriteTexture()
{
	bool	ret = _pSprite->RemoveTexture( _uSprNumb ) == S_OK;
	ASSERT( ret && "can't remove sprite texture" );
	return ret;
}


bool CConvWrapper::GetSpriteTextureInfo(String ^&pStr)
{
	const uint	u_buf_size = 255;
	char		a_buffer[u_buf_size];

	bool	ret = _pSprite->GetTextureInfo( _uSprNumb, a_buffer, u_buf_size ) == S_OK;
	ASSERT( ret && "can't get sprite texture info" );

	if ( ret )
		pStr = gcnew String( a_buffer );

	return ret;
}


bool CConvWrapper::GetSpriteNames(ListBox ^pList)
{
	const uint	u_buf_size = 255;
	char		a_buffer[u_buf_size];
	uint		u_count = 0;

	bool	ret = _pSprite->GetTexturesCount( u_count ) == S_OK;
	ASSERT( ret && "can't get sprite textures count" );
	ret &= u_count != 0;

	pList->Items->Clear();

	if ( ret )
	{
		for (uint i = 0; i < u_count; ++i)
		{
			ret = _pSprite->GetName( i, a_buffer, u_buf_size ) == S_OK;
			ASSERT( ret && "can't get sprite texture name" );

			if ( !ret )
				break;

			pList->Items->Add( gcnew String( a_buffer ) );
		}
	}
	return ret;
}


bool CConvWrapper::SetSpriteFrame(uint x, uint y)
{
	bool	ret = _pSprite->SetFrame( _uSprNumb, x, y ) == S_OK;
	ASSERT( ret && "can't set sprite frame dimension" );
	return ret;
}


bool CConvWrapper::GetSpriteFrame(uint &x, uint &y)
{
	bool	ret = _pSprite->GetFrame( _uSprNumb, x, y ) == S_OK;
	ASSERT( ret && "can't get sprite frame dimension" );
	return ret;
}


bool CConvWrapper::AddSpriteFrame(uint uIndex, uint uARGB)
{
	_aFrames.push_back( TSpriteFrame( uIndex, TRGBA( TARGB( uARGB ) ).uRGBA ) );
	return true;
}


bool CConvWrapper::GetSpriteFrame(uint uNumb, uint &uIndex, uint &uARGB)
{
	if ( uNumb < _aFrames.size() )
	{
		uIndex = _aFrames[uNumb].uIndex;
		uARGB  = TARGB( TRGBA( _aFrames[uNumb].uColor ) ).uARGB;
		return true;
	}
	return false;
}


bool CConvWrapper::RemoveSpriteFrame(uint uNumb)
{
	if ( uNumb < _aFrames.size() )
	{
		_aFrames.erase( _aFrames.begin() + uNumb );
		return true;
	}
	return false;
}


bool CConvWrapper::MoveUpSpriteFrame(uint uNumb)
{
	if ( uNumb != 0 && uNumb < _aFrames.size() )
	{
		TSpriteFrame	s_temp = _aFrames[uNumb];
		_aFrames[uNumb]   = _aFrames[uNumb-1];
		_aFrames[uNumb-1] = s_temp;
		return true;
	}
	return false;
}


bool CConvWrapper::MoveDownSpriteFrame(uint uNumb)
{
	if ( uNumb < _aFrames.size()-1 && _aFrames.size() != 0 )
	{
		TSpriteFrame	s_temp = _aFrames[uNumb];
		_aFrames[uNumb]   = _aFrames[uNumb+1];
		_aFrames[uNumb+1] = s_temp;
		return true;
	}
	return false;
}


bool CConvWrapper::GetSpriteFrames(ListBox ^pList)
{
	pList->Items->Clear();

	std::string	str;
	char		a_buf[30];
	char		a_zero[7] = "000000";

	for (size_t i = 0; i < _aFrames.size(); ++i)
	{
		str  = itoa( _aFrames[i].uIndex, a_buf, 10 );
		str += "   ";

		itoa( _aFrames[i].uColor, a_buf, 16 );
		str.append( a_zero, strlen(a_buf)-6 );
		
		str += a_buf;

		pList->Items->Add( gcnew String( str.c_str() ) );
	}
	return true;
}


bool CConvWrapper::ClearSpriteFrames()
{
	_aFrames.clear();
	return true;
}


bool CConvWrapper::AddSpriteAnimation(String ^pName, float fFrameRate)
{
	TCLIString			sName( pName );
	uint				u_anim_numb = -1;

	if ( sName[0] == 0 || _aFrames.size() == 0 ) {
		ASSERT( false && "name or indices string are empty" );
		return false;
	}

	bool	ret = _pSprite->SetAnimation( _uSprNumb, sName, fFrameRate, &_aFrames[0], _aFrames.size(), u_anim_numb ) == S_OK;
	ASSERT( ret && "can't set sprite animation" );

	return ret;
}


bool CConvWrapper::RemoveSpriteAnimation()
{
	bool	ret = _pSprite->RemoveAnimationN( _uSprNumb, _uAnimNumb ) == S_OK;
	ASSERT( ret && "can't remove sprite animation" );
	return ret;
}


bool CConvWrapper::GetSpriteAnimationNames(ComboBox ^pComboBox)
{
	const uint		u_buf_size = 255;
	const uint		u_idx_size = 255;
	char			a_buffer[u_buf_size];
	TSpriteFrame	a_idx_buffer[u_idx_size];
	uint			u_count = 0;
	uint			u_idx_count = 0;
	float			f_frame_rate = 0.f;
	bool			ret = true;

	ret = _pSprite->GetAnimationCount( _uSprNumb, u_count ) == S_OK;
	ASSERT( ret && "can't get sprite animations count" );

	pComboBox->Items->Clear();

	for (uint i = 0; i < u_count && ret; ++i)
	{
		ret = _pSprite->GetAnimation( _uSprNumb, i, a_buffer, u_buf_size, f_frame_rate,
									  a_idx_buffer, u_idx_size, u_idx_count ) == S_OK;
		ASSERT( ret && "can't get sprite animation" );

		if ( !ret )
			break;

		pComboBox->Items->Add( gcnew String( a_buffer ) );
	}

	return ret;
}


bool CConvWrapper::GetSpriteAnimation(String ^&pName, ListBox ^pFrames, float &fFrameRate)
{
	const uint		u_buf_size = 255;
	char			a_buffer[u_buf_size]	 = {0};
	uint			u_count = 0;
	std::string		str;
	
	_aFrames.resize( 255 );

	bool		ret = _pSprite->GetAnimation( _uSprNumb, _uAnimNumb, a_buffer, u_buf_size, fFrameRate,
											  &_aFrames[0], _aFrames.size(), u_count ) == S_OK;
	ret &= u_count != 0;
	ASSERT( ret && "can't get sprite animation" );

	if ( ret )
	{
		pName = gcnew String( a_buffer );

		_aFrames.resize( u_count );
		ret = GetSpriteFrames( pFrames );
	}

	return ret;
}


bool CConvWrapper::ChangeSpriteAnimation(String ^pName, float fFrameRate)
{
	bool	ret = true;
	
	if ( (ret = RemoveSpriteAnimation()) )
		ret = AddSpriteAnimation( pName, fFrameRate );

	return ret;
}


bool CConvWrapper::GetSpriteInfo(String ^&pStr)
{
	const uint	u_buf_size = 255;
	char		a_buffer[u_buf_size];

	bool	ret = _pSprite->GetInfo( a_buffer, u_buf_size ) == S_OK;
	ASSERT( ret && "can't get sprite info" );

	if ( ret )
		pStr = gcnew String( a_buffer );
	
	return ret;
}


bool CConvWrapper::GetSpriteFormat(TTextureFormat &sFormat)
{
	bool	ret = _pSprite->GetFormat( sFormat ) == S_OK;
	ASSERT( ret && "can't get sprite format" );
	return ret;
}


bool CConvWrapper::SetSpriteFormat(const TTextureFormat &sFormat)
{
	bool	ret = _pSprite->SetFormat( sFormat ) == S_OK;
	ASSERT( ret && "can't set sprite format" );
	return ret;
}


bool CConvWrapper::GetSpriteParams(TSpriteParams &sParams)
{
	bool	ret = _pSprite->GetParams( sParams ) == S_OK;
	ASSERT( ret && "can't get sprite params" );
	return ret;
}


bool CConvWrapper::SetSpriteParams(const TSpriteParams &sParams)
{
	bool	ret = _pSprite->SetParams( sParams ) == S_OK;
	ASSERT( ret && "can't set sprite params" );
	return ret;
}



///////////////////////// SOUND ///////////////////////////

bool CConvWrapper::GetSoundName(String ^&pStr)
{
	if ( _sSoundName.empty() )
		return false;

	pStr = gcnew String( _sSoundName.c_str() );
	return true;
}


bool CConvWrapper::GetSupportedSoundFormats(String ^&pStr)
{
	const uint	u_buf_size = 255;
	char		a_buffer[u_buf_size];

	bool	ret = _pSound->GetSupportedFormats( a_buffer, u_buf_size ) == S_OK;
	ASSERT( ret && "can't get supported sound formats" );

	if ( ret ) {
		pStr = gcnew String( a_buffer );
		pStr += L"|all files|*.*";
	}

	return ret;
}


bool CConvWrapper::DeleteSound()
{
	bool	ret = _pSound->Delete() == S_OK;
	ASSERT( ret && "can't delete sound" );
	_sSoundName.clear();
	return ret;
}


bool CConvWrapper::LoadSound(String ^pStr)
{
	TCLIString	str(pStr);

	bool	ret = _pSound->Load( str ) == S_OK;
	ASSERT( ret && "can't load sound" );

	if ( ret )
		_sSoundName = GetFileName( str );

	return ret;
}


bool CConvWrapper::SaveSound(String ^pStr)
{
	TCLIString	str(pStr);

	bool	ret = _pSound->Save( str ) == S_OK;
	ASSERT( ret && "can't save sound" );

	return ret;
}


bool CConvWrapper::SetSoundParams(const TSoundParams &sParams)
{
	bool	ret = _pSound->SetParams( sParams ) == S_OK;
	ASSERT( ret && "can't set sound params" );
	return ret;
}


bool CConvWrapper::GetSoundParams(TSoundParams &sParams)
{
	bool	ret = _pSound->GetParams( sParams ) == S_OK;
	ASSERT( ret && "can't get sound params" );
	return ret;
}


bool CConvWrapper::GetSoundInfo(String ^&pStr)
{
	const uint	u_buf_size = 255;
	char		a_buffer[u_buf_size];

	bool	ret = _pSound->GetInfo( a_buffer, u_buf_size ) == S_OK;
	ASSERT( ret && "can't get sound info" );

	if ( ret )
		pStr = gcnew String( a_buffer );

	return ret;
}

